package com.hengpeng.itfin.service.impl;

import java.util.Date;
import java.util.List;

import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hengpeng.common.exception.ServiceResult;
import com.hengpeng.common.exception.ServiceResultFactory;
import com.hengpeng.common.persist.entity.AbstractEntity.BoolValue;
import com.hengpeng.common.persist.query.DynamicQuery;
import com.hengpeng.common.util.DateTimeUtil;
import com.hengpeng.itfin.common.Configuration;
import com.hengpeng.itfin.exception.TransException;
import com.hengpeng.itfin.service.PaymentService;
import com.hengpeng.itfin.tools.PoolServer;
import com.hengpeng.itfinbase.constants.RespCodeConstants;
import com.hengpeng.itfinbase.constants.TransCodeConstants;
import com.hengpeng.itfinbase.en.AccountType;
import com.hengpeng.itfinbase.en.TradeMode;
import com.hengpeng.itfinbase.en.TransType;
import com.hengpeng.itfinbase.idAssign.ID;
import com.hengpeng.itfinbase.message.partner.CashRequestMsg;
import com.hengpeng.itfinbase.message.partner.CashResponseMsg;
import com.hengpeng.itfinbase.message.partner.DrawReconciliationRequestMsg;
import com.hengpeng.itfinbase.message.partner.DrawReconciliationResponseMsg;
import com.hengpeng.itfinbase.message.partner.DrawReconciliationResponseMsg.CashReconciliationDto;
import com.hengpeng.itfinbase.message.partner.PartnerTransType;
import com.hengpeng.itfinbase.message.partner.PayRequestMsg;
import com.hengpeng.itfinbase.message.partner.PayResponseMsg;
import com.hengpeng.itfinbase.message.partner.SaveReconciliationRequestMsg;
import com.hengpeng.itfinbase.message.partner.SaveReconciliationResponseMsg;
import com.hengpeng.itfinbase.message.partner.SaveReconciliationResponseMsg.SaveReconciliationDto;
import com.hengpeng.itfinbase.persist.Account;
import com.hengpeng.itfinbase.persist.AccountLog;
import com.hengpeng.itfinbase.persist.Payment;
import com.hengpeng.itfinbase.persist.Payment.PayStatus;
import com.hengpeng.itfinbase.persist.Payment.PaymentType;
import com.hengpeng.itfinbase.persist.UserBankCard;
import com.hengpeng.itfinbase.persist.UserInfo;

/**
 * <pre>
 * 支付系统服务实现
 * </pre>
 * 
 * @author zhaojitao
 * @version 1.0, 2015-6-4
 */
@Service
@Lazy
@Transactional
public class PaymentServiceImpl extends BaseServiceImpl implements PaymentService {
    @Override
    public void packPayRequest(PayRequestMsg request) {
        if (!serviceFactory.getPartnerService().isTrustPattern()) {
            // 设置测试金额
            String isPayTest = Configuration.getValue("pay.test");
            String testMoney = Configuration.getValue("pay.money");
            if (isPayTest != null && testMoney != null && isPayTest.equals("true")) {
                request.setTransAmt(testMoney);
            }
        }
        Payment payment = new Payment();
        payment.setType(PaymentType.IMPREST);
        payment.setProviderId(request.getProviderId());
        if (request.getAccountType() == AccountType.PLATFORM) {// 平台充值
            String orderId = ID.getInstanse().getID(18).toString();
            UserInfo user = serviceFactory.getDaoFactory().getUserInfoDao().get(request.getUserId());
            if (user == null) {
                throw new TransException("用户不存在！");
            }
            request.setOrdId(orderId);
            request.setOrdDate(DateTimeUtil.formatToStr(new Date(), DateTimeUtil.DATE_FORMAT_YYYYMMDD));
            request.setUsrCustId(user.getTrustAccountId());
        } else {
            UserInfo user = serviceFactory.getDaoFactory().getUserInfoDao().get(request.getUserId());
            if (user == null) {
                throw new TransException("用户不存在！");
            }
            Account account = serviceFactory.getAccountService().getAccount(user.getId());
            String orderId = ID.getInstanse().getID(18).toString();
            request.setOrdId(orderId);
            request.setOrdDate(DateTimeUtil.formatToStr(new Date(), DateTimeUtil.DATE_FORMAT_YYYYMMDD));
            request.setUsrCustId(user.getTrustAccountId());
            Double doubleMoney = Double.parseDouble(request.getTransAmt()) * 100;
            payment.setMoney(doubleMoney.longValue());
            payment.setUserId(request.getUserId());
            payment.setAccountType(request.getAccountType());
            payment.setCreateTime(new Date());
            payment.setIsReconcil(BoolValue.NO);
            payment.setOrderId(orderId);
            payment.setRequestTime(new Date());
            payment.setStatus(PayStatus.PAYING);
            payment.setTrustAccountId(request.getUsrCustId());
            payment.setUserAgent(request.getUserAgent());
            payment.setUserName(user.getUserName());
            payment.setAccountId(account.getId());
        }
        serviceFactory.getDaoFactory().getCommonDao().saveEntity(payment);
    }

    @Override
    public ServiceResult<Payment> dealPayResult(PayResponseMsg msg) {
        Payment payment = serviceFactory.getPaymentService().findByOrderId(msg.getOrdId());
        if (payment != null) {
            if (payment.getStatus() == PayStatus.PAYING) {
                if (msg.getRespCode().equals(RespCodeConstants.CommonCode.TRANS_SUC)) {
                    Double feeAmt = Double.parseDouble(msg.getFeeAmt().replaceAll(",", "")) * 100;
                    int i = serviceFactory
                            .getDaoFactory()
                            .getPaymentDao()
                            .updateStatus(PayStatus.PAYING, PayStatus.SUCCESS, new Date(), new Date(),
                                    feeAmt.longValue(), msg.getOrdId());
                    if (i > 0) {
                        serviceFactory.getAccountService().add(payment.getUserId(), TransType.IMPREST,
                                Long.parseLong(String.valueOf(payment.getMoney())), String.valueOf(payment.getId()),
                                "充值成功");
                    }
                    // UserInfo user =
                    // serviceFactory.getUserInfoService().getUserByTrustAccountId(msg.getFeeCustId());
                    // if (feeAmt > 0d)
                    // {
                    // serviceFactory.getAccountService().changeAccountMoney(user.getId(),
                    // feeAmt.longValue(),
                    // TransType.IMPREST_FEE, AccountLog.TradeMode.SUBTRACT,
                    // payment.getId().toString(),
                    // "充值手续费");
                    // }
                } else {
                    serviceFactory
                            .getDaoFactory()
                            .getPaymentDao()
                            .updateStatus(PayStatus.PAYING, PayStatus.FAILED, new Date(), new Date(), 0l,
                                    msg.getOrdId());
                }
            }
            return ServiceResultFactory.getServiceResult(RespCodeConstants.CommonCode.TRANS_SUC, payment);
        } else {
            // 未找到充值记录
            return ServiceResultFactory.getServiceResult(RespCodeConstants.CommonCode.DATA_NOT_FOUND, Payment.class);
        }
    }

    @Override
    public void packDrawRequest(CashRequestMsg request) {
        Payment payment = new Payment();
        payment.setType(PaymentType.DRAW);
        payment.setProviderId(request.getProviderId());
        if (request.getAccountType() == AccountType.PLATFORM) {
            // 平台取现，暂不记录本地记录
            UserInfo user = serviceFactory.getDaoFactory().getUserInfoDao().get(request.getUserId());
            if (user == null) {
                throw new TransException("用户不存在！");
            }
            String orderId = ID.getInstanse().getID(18).toString();
            request.setOrdId(orderId);
            request.setOrdDate(DateTimeUtil.formatToStr(new Date(), DateTimeUtil.DATE_FORMAT_YYYYMMDD));
            request.setUsrCustId(user.getTrustAccountId());
        } else {
            UserInfo user = serviceFactory.getDaoFactory().getUserInfoDao().get(request.getUserId());
            if (user == null) {
                throw new TransException("用户不存在！");
            }
            if (!serviceFactory.getPartnerService().isTrustPattern()) {
                UserBankCard bankCard = serviceFactory.getPersistService().get(UserBankCard.class,
                        request.getBankCardId());
                if (bankCard == null) {
                    throw new TransException("银行卡不存在！");
                }
                payment.setBankName(bankCard.getBankName().getText());
            }
            Double doubleMoney = Double.parseDouble(request.getTransAmt()) * 100;
            Account account = serviceFactory.getAccountService().getAccount(user.getId());
            if (account.getBaseMoney() - account.getFreezeMoney() < doubleMoney) {
                throw new TransException("金额不足！");
            }
            String orderId = ID.getInstanse().getID(18).toString();
            request.setOrdId(orderId);
            request.setOrdDate(DateTimeUtil.formatToStr(new Date(), DateTimeUtil.DATE_FORMAT_YYYYMMDD));
            request.setUsrCustId(user.getTrustAccountId());
            payment.setMoney(doubleMoney.longValue());
            payment.setUserId(request.getUserId());
            payment.setAccountType(request.getAccountType());
            payment.setCreateTime(new Date());
            payment.setIsReconcil(BoolValue.NO);
            payment.setOrderId(orderId);
            payment.setRequestTime(new Date());
            payment.setStatus(PayStatus.PAYING);
            payment.setTrustAccountId(request.getUsrCustId());
            payment.setUserAgent(request.getUserAgent());
            payment.setUserName(user.getUserName());
            payment.setAccountId(account.getId());
            serviceFactory.getDaoFactory().getCommonDao().saveEntity(payment);
            serviceFactory.getAccountService().freeze(payment.getUserId(), TransType.DRAW,
                    Long.parseLong(String.valueOf(payment.getMoney())), String.valueOf(payment.getId()), "提现冻结");
        }
    }

    @Override
    public ServiceResult<Payment> dealDrawResult(CashResponseMsg msg) {
        Payment payment = serviceFactory.getPaymentService().findByOrderId(msg.getOrdId());
        if (payment != null) {
            if (payment.getStatus() == PayStatus.PAYING) {
                if (msg.getRespCode().equals(RespCodeConstants.CommonCode.TRANS_SUC)) {
                    Double feeAmt = Double.parseDouble(msg.getFeeAmt().replaceAll(",", "")) * 100;
                    int i = serviceFactory
                            .getDaoFactory()
                            .getPaymentDao()
                            .updateStatus(PayStatus.PAYING, PayStatus.SUCCESS, new Date(), new Date(),
                                    feeAmt.longValue(), msg.getOrdId());
                    if (i > 0) {
                        serviceFactory.getAccountService().unfreezeForSuc(payment.getUserId(), TransType.DRAW,
                                Long.parseLong(String.valueOf(payment.getMoney())), String.valueOf(payment.getId()),
                                "提现成功");

                        UserInfo user = serviceFactory.getUserInfoService().getUserByTrustAccountId(msg.getFeeCustId());
                        if (feeAmt > 0d) {
                            serviceFactory.getAccountService().changeAccountMoney(user.getId(), feeAmt.longValue(),
                                    TransType.DRAW_FEE, TradeMode.SUBTRACT, String.valueOf(payment.getId()), "提现手续费");
                        }
                    }
                } else if (msg.getRespCode().equals(RespCodeConstants.CommonCode.TRANSMESSAGE_ERRCODE_DEALING)) {// 处理中

                } else if (msg.getRespCode().equals(RespCodeConstants.AccountCode.CASH_ERRCODE_FAIL)) {// 失败
                    int i = serviceFactory
                            .getDaoFactory()
                            .getPaymentDao()
                            .updateStatus(PayStatus.PAYING, PayStatus.FAILED, new Date(), new Date(), 0l,
                                    msg.getOrdId());
                    if (i > 0) {
                        serviceFactory.getAccountService().unfreezeForFail(payment.getUserId(), TransType.DRAW,
                                Long.parseLong(String.valueOf(payment.getMoney())), String.valueOf(payment.getId()),
                                "提现失败解冻");
                    }
                }
            }
            return ServiceResultFactory.getServiceResult(RespCodeConstants.CommonCode.TRANS_SUC, payment);
        } else {
            // 未找到充值记录
            return ServiceResultFactory.getServiceResult(RespCodeConstants.CommonCode.DATA_NOT_FOUND, Payment.class);

        }
    }

    @Override
    public Payment findByOrderId(String orderId) {
        DynamicQuery query = new DynamicQuery(Payment.class);
        query.eq("orderId", orderId);
        return serviceFactory.getPersistService().getByDynamicQuery(Payment.class, query);
    }

    @Override
    public Payment findByOrderIdAndProviderId(String orderId, String providerId) {
        DynamicQuery query = new DynamicQuery(Payment.class);
        query.eq("orderId", orderId);
        query.eq("providerId", providerId);
        return serviceFactory.getPersistService().getByDynamicQuery(Payment.class, query);
    }

    @Override
    public void saveReconciliation(Integer pageNum, Integer pageSize, Date beginDate, Date endDate) {
        SaveReconciliationResponseMsg responseMsg = serviceFactory.getPaymentService().doSaveReconciliation(pageNum,
                pageSize, beginDate, endDate);
        Integer totalItems = Integer.parseInt(responseMsg.getTotalItems());
        if (totalItems != null && (pageNum * pageSize) > totalItems) {
            saveReconciliation(pageNum + 1, pageSize, beginDate, endDate);
        } else {
            return;
        }
    }

    @Override
    public SaveReconciliationResponseMsg doSaveReconciliation(Integer pageNum, Integer pageSize, Date beginDate,
            Date endDate) {
        SaveReconciliationRequestMsg reqMsg = new SaveReconciliationRequestMsg();
        reqMsg.setBeginDate(DateTimeUtil.formatToStr(beginDate, DateTimeUtil.DATE_FORMAT_YYYYMMDD));
        reqMsg.setEndDate(DateTimeUtil.formatToStr(endDate, DateTimeUtil.DATE_FORMAT_YYYYMMDD));
        reqMsg.setPageNum(pageNum.toString());
        reqMsg.setPageSize(pageSize.toString());
        reqMsg.setPartnerTransType(PartnerTransType.SaveReconciliation);
        reqMsg.setTransType(TransCodeConstants.PartnerTransCode.REQUEST);
        SaveReconciliationResponseMsg responseMsg = (SaveReconciliationResponseMsg) serviceFactory.getPartnerService()
                .request(reqMsg);
        /**
         * 处理结果
         */
        List<SaveReconciliationDto> reconciliationInfos = responseMsg.getSaveReconciliationDtoList();
        if (reconciliationInfos != null && reconciliationInfos.size() > 0) {
            PoolServer poolServer = new PoolServer(50);
            for (SaveReconciliationDto dto : reconciliationInfos) {
                final PayResponseMsg payResponseMsg = new PayResponseMsg();
                payResponseMsg.setOrdId(dto.getOrdId());
                if ("S".equals(dto.getTransStat())) {// 成功
                    payResponseMsg.setRespCode(RespCodeConstants.CommonCode.TRANS_SUC);
                    payResponseMsg.setRespDesc(RespCodeConstants.CommonCode.TRANS_SUC_MSG);
                } else if ("F".equals(dto.getTransStat())) {// 失败
                    payResponseMsg.setRespCode(RespCodeConstants.CommonCode.TRANS_FAIL);
                    payResponseMsg.setRespDesc(RespCodeConstants.CommonCode.TRANS_FAIL_MSG);
                } else if ("I".equals(dto.getTransStat())) {// 初始
                    /**
                     * 初始状态：用户还没有输入密码确认的充值 初始状态暂不处理
                     */
                }
                poolServer.executeTask(new Runnable() {
                    @Override
                    public void run() {
                        serviceFactory.getPaymentService().dealPayResult(payResponseMsg);
                    }
                });
            }
            poolServer.endServer();
        }
        return responseMsg;
    }

    @Override
    public void drawReconciliation(Integer pageNum, Integer pageSize, Date beginDate, Date endDate) {
        DrawReconciliationResponseMsg responseMsg = serviceFactory.getPaymentService().doDrawReconciliation(pageNum,
                pageSize, beginDate, endDate);
        Integer totalItems = Integer.parseInt(responseMsg.getTotalItems());
        if (totalItems != null && (pageNum * pageSize) > totalItems) {
            drawReconciliation(pageNum + 1, pageSize, beginDate, endDate);
        } else {
            return;
        }
    }

    @Override
    public DrawReconciliationResponseMsg doDrawReconciliation(Integer pageNum, Integer pageSize, Date beginDate,
            Date endDate) {
        DrawReconciliationRequestMsg reqMsg = new DrawReconciliationRequestMsg();
        reqMsg.setBeginDate(DateTimeUtil.formatToStr(beginDate, DateTimeUtil.DATE_FORMAT_YYYYMMDD));
        reqMsg.setEndDate(DateTimeUtil.formatToStr(endDate, DateTimeUtil.DATE_FORMAT_YYYYMMDD));
        reqMsg.setPageNum(pageNum.toString());
        reqMsg.setPageSize(pageSize.toString());
        reqMsg.setPartnerTransType(PartnerTransType.CashReconciliation);
        reqMsg.setTransType(TransCodeConstants.PartnerTransCode.REQUEST);
        DrawReconciliationResponseMsg responseMsg = (DrawReconciliationResponseMsg) serviceFactory.getPartnerService()
                .request(reqMsg);
        /**
         * 处理结果
         */
        List<CashReconciliationDto> reconciliationInfos = responseMsg.getCashReconciliationDtoList();
        if (reconciliationInfos != null && reconciliationInfos.size() > 0) {
            PoolServer poolServer = new PoolServer(50);
            for (CashReconciliationDto dto : reconciliationInfos) {
                final CashResponseMsg cashResponseMsg = new CashResponseMsg();
                cashResponseMsg.setOrdId(dto.getOrdId());
                if ("S".equals(dto.getTransStat())) {// 成功
                    cashResponseMsg.setRespCode(RespCodeConstants.CommonCode.TRANS_SUC);
                    cashResponseMsg.setRespDesc(RespCodeConstants.CommonCode.TRANS_SUC_MSG);
                } else if ("F".equals(dto.getTransStat())) {// 失败
                    cashResponseMsg.setRespCode(RespCodeConstants.AccountCode.CASH_ERRCODE_FAIL);
                } else if ("I".equals(dto.getTransStat())) {// 初始
                    cashResponseMsg.setRespCode(RespCodeConstants.CommonCode.TRANSMESSAGE_ERRCODE_DEALING);
                } else if ("H".equals(dto.getTransStat())) {// 经办
                    cashResponseMsg.setRespCode(RespCodeConstants.CommonCode.TRANSMESSAGE_ERRCODE_DEALING);
                } else if ("R".equals(dto.getTransStat())) {// 拒绝
                    cashResponseMsg.setRespCode(RespCodeConstants.AccountCode.CASH_ERRCODE_FAIL);
                }
                poolServer.executeTask(new Runnable() {
                    @Override
                    public void run() {
                        serviceFactory.getPaymentService().dealDrawResult(cashResponseMsg);
                    }
                });
            }
            poolServer.endServer();
        }
        return responseMsg;
    }
}
